/************
 *      CH32V30x_D8C
 */
#ifndef SYSTEM_HPP
#define SYSTEM_HPP

#include <stdint.h>

extern "C" {

/************ RISCV ************/

typedef struct PFIC_Register {
    volatile  uint32_t ISR[8];
    volatile  uint32_t IPR[8];
    volatile uint32_t ITHRESDR;
    volatile uint32_t RESERVED;
    volatile uint32_t CFGR;
    volatile  uint32_t GISR;
    volatile uint8_t VTFIDR[4];
    uint8_t RESERVED0[12];
    volatile uint32_t VTFADDR[4];
    uint8_t RESERVED1[0x90];
    volatile  uint32_t IENR[8];
    uint8_t RESERVED2[0x60];
    volatile  uint32_t IRER[8];
    uint8_t RESERVED3[0x60];
    volatile  uint32_t IPSR[8];
    uint8_t RESERVED4[0x60];
    volatile  uint32_t IPRR[8];
    uint8_t RESERVED5[0x60];
    volatile uint32_t IACTR[8];
    uint8_t RESERVED6[0xE0];
    volatile uint8_t IPRIOR[256];
    uint8_t RESERVED7[0x810];
    volatile uint32_t SCTLR;
} PFIC_Register_t;

typedef struct SysTick_Register{
    volatile uint32_t CTLR;
    volatile uint32_t SR;
    volatile uint64_t CNT;
    volatile uint64_t CMP;
} SysTick_Register_t;

/************ PERIPHERAL ************/

typedef struct ADC_Register {
    volatile uint32_t STATR;
    volatile uint32_t CTLR1;
    volatile uint32_t CTLR2;
    volatile uint32_t SAMPTR1;
    volatile uint32_t SAMPTR2;
    volatile uint32_t IOFR1;
    volatile uint32_t IOFR2;
    volatile uint32_t IOFR3;
    volatile uint32_t IOFR4;
    volatile uint32_t WDHTR;
    volatile uint32_t WDLTR;
    volatile uint32_t RSQR1;
    volatile uint32_t RSQR2;
    volatile uint32_t RSQR3;
    volatile uint32_t ISQR;
    volatile uint32_t IDATAR1;
    volatile uint32_t IDATAR2;
    volatile uint32_t IDATAR3;
    volatile uint32_t IDATAR4;
    volatile uint32_t RDATAR;
    uint32_t  RESERVED0;
    volatile uint32_t AUX;
} ADC_Register_t;

typedef struct BKP_Register {
    uint32_t  RESERVED0;
    volatile uint16_t DATAR1;
    uint16_t  RESERVED1;
    volatile uint16_t DATAR2;
    uint16_t  RESERVED2;
    volatile uint16_t DATAR3;
    uint16_t  RESERVED3;
    volatile uint16_t DATAR4;
    uint16_t  RESERVED4;
    volatile uint16_t DATAR5;
    uint16_t  RESERVED5;
    volatile uint16_t DATAR6;
    uint16_t  RESERVED6;
    volatile uint16_t DATAR7;
    uint16_t  RESERVED7;
    volatile uint16_t DATAR8;
    uint16_t  RESERVED8;
    volatile uint16_t DATAR9;
    uint16_t  RESERVED9;
    volatile uint16_t DATAR10;
    uint16_t  RESERVED10; 
    volatile uint16_t OCTLR;
    uint16_t  RESERVED11;
    volatile uint16_t TPCTLR;
    uint16_t  RESERVED12;
    volatile uint16_t TPCSR;
    uint16_t  RESERVED13[5];
    volatile uint16_t DATAR11;
    uint16_t  RESERVED14;
    volatile uint16_t DATAR12;
    uint16_t  RESERVED15;
    volatile uint16_t DATAR13;
    uint16_t  RESERVED16;
    volatile uint16_t DATAR14;
    uint16_t  RESERVED17;
    volatile uint16_t DATAR15;
    uint16_t  RESERVED18;
    volatile uint16_t DATAR16;
    uint16_t  RESERVED19;
    volatile uint16_t DATAR17;
    uint16_t  RESERVED20;
    volatile uint16_t DATAR18;
    uint16_t  RESERVED21;
    volatile uint16_t DATAR19;
    uint16_t  RESERVED22;
    volatile uint16_t DATAR20;
    uint16_t  RESERVED23;
    volatile uint16_t DATAR21;
    uint16_t  RESERVED24;
    volatile uint16_t DATAR22;
    uint16_t  RESERVED25;
    volatile uint16_t DATAR23;
    uint16_t  RESERVED26;
    volatile uint16_t DATAR24;
    uint16_t  RESERVED27;
    volatile uint16_t DATAR25;
    uint16_t  RESERVED28;
    volatile uint16_t DATAR26;
    uint16_t  RESERVED29;
    volatile uint16_t DATAR27;
    uint16_t  RESERVED30;
    volatile uint16_t DATAR28;
    uint16_t  RESERVED31;
    volatile uint16_t DATAR29;
    uint16_t  RESERVED32;
    volatile uint16_t DATAR30;
    uint16_t  RESERVED33; 
    volatile uint16_t DATAR31;
    uint16_t  RESERVED34;
    volatile uint16_t DATAR32;
    uint16_t  RESERVED35;
    volatile uint16_t DATAR33;
    uint16_t  RESERVED36;
    volatile uint16_t DATAR34;
    uint16_t  RESERVED37;
    volatile uint16_t DATAR35;
    uint16_t  RESERVED38;
    volatile uint16_t DATAR36;
    uint16_t  RESERVED39;
    volatile uint16_t DATAR37;
    uint16_t  RESERVED40;
    volatile uint16_t DATAR38;
    uint16_t  RESERVED41;
    volatile uint16_t DATAR39;
    uint16_t  RESERVED42;
    volatile uint16_t DATAR40;
    uint16_t  RESERVED43;
    volatile uint16_t DATAR41;
    uint16_t  RESERVED44;
    volatile uint16_t DATAR42;
    uint16_t  RESERVED45; 
} BKP_Register_t;

typedef struct CAN_TxMailBox_Register {
    volatile uint32_t TXMIR;
    volatile uint32_t TXMDTR;
    volatile uint32_t TXMDLR;
    volatile uint32_t TXMDHR;
} CAN_TxMailBox_Register_t;

typedef struct CAN_FIFOMailBox_Register {
    volatile uint32_t RXMIR;
    volatile uint32_t RXMDTR;
    volatile uint32_t RXMDLR;
    volatile uint32_t RXMDHR;
} CAN_FIFOMailBox_Register_t;

typedef struct CAN_Filter_Register {
    volatile uint32_t FR1;
    volatile uint32_t FR2;
} CAN_Filter_Register_t;

typedef struct CAN_Register {
    volatile uint32_t CTLR;
    volatile uint32_t STATR;
    volatile uint32_t TSTATR;
    volatile uint32_t RFIFO0;
    volatile uint32_t RFIFO1;
    volatile uint32_t INTENR;
    volatile uint32_t ERRSR;
    volatile uint32_t BTIMR;
    uint32_t  RESERVED0[88];
    CAN_TxMailBox_Register_t sTxMailBox[3];
    CAN_FIFOMailBox_Register_t sFIFOMailBox[2];
    uint32_t  RESERVED1[12];
    volatile uint32_t FCTLR;
    volatile uint32_t FMCFGR;
    uint32_t  RESERVED2;
    volatile uint32_t FSCFGR;
    uint32_t  RESERVED3;
    volatile uint32_t FAFIFOR;
    uint32_t  RESERVED4;
    volatile uint32_t FWR;
    uint32_t  RESERVED5[8];
    CAN_Filter_Register_t sFilterRegister[28];
} CAN_Register_t;

typedef struct CRC_Register {
    volatile uint32_t DATAR;
    volatile uint8_t  IDATAR;
    uint8_t   RESERVED0;
    uint16_t  RESERVED1;
    volatile uint32_t CTLR;
} CRC_Register_t;

typedef struct DAC_Register {
    volatile uint32_t CTLR;
    volatile uint32_t SWTR;
    volatile uint32_t R12BDHR1;
    volatile uint32_t L12BDHR1;
    volatile uint32_t R8BDHR1;
    volatile uint32_t R12BDHR2;
    volatile uint32_t L12BDHR2;
    volatile uint32_t R8BDHR2;
    volatile uint32_t RD12BDHR;
    volatile uint32_t LD12BDHR;
    volatile uint32_t RD8BDHR;
    volatile uint32_t DOR1;
    volatile uint32_t DOR2;
} DAC_Register_t;

typedef struct DMA_Channel_Register {
    volatile uint32_t CFGR;
    volatile uint32_t CNTR;
    volatile uint32_t PADDR;
    volatile uint32_t MADDR;
} DMA_Channel_Register_t;

typedef struct DMA_Register {
    volatile uint32_t INTFR;
    volatile uint32_t INTFCR;
} DMA_Register_t;

typedef struct EXTI_Register {
    volatile uint32_t INTENR; 
    volatile uint32_t EVENR;   
    volatile uint32_t RTENR;   
    volatile uint32_t FTENR;   
    volatile uint32_t SWIEVR;  
    volatile uint32_t INTFR;   
} EXTI_Register_t;

typedef struct FLASH_Register {
    volatile uint32_t ACTLR;
    volatile uint32_t KEYR;
    volatile uint32_t OBKEYR;
    volatile uint32_t STATR;
    volatile uint32_t CTLR;
    volatile uint32_t ADDR;
    volatile uint32_t RESERVED;
    volatile uint32_t OBR;
    volatile uint32_t WPR;
    volatile uint32_t MODEKEYR;
} FLASH_Register_t;

typedef struct OB_Register {
    volatile uint16_t RDPR;
    volatile uint16_t USER;
    volatile uint16_t Data0;
    volatile uint16_t Data1;
    volatile uint16_t WRPR0;
    volatile uint16_t WRPR1;
    volatile uint16_t WRPR2;
    volatile uint16_t WRPR3;
} OB_Register_t;

typedef struct FSMC_Bank1_Register {
    volatile uint32_t BTCR[8];
} FSMC_Bank1_Register_t;

typedef struct FSMC_Bank1E_Register {
    volatile uint32_t BWTR[7];
} FSMC_Bank1E_Register_t;

typedef struct FSMC_Bank2_Register {
    volatile uint32_t PCR2;
    volatile uint32_t SR2;
    volatile uint32_t PMEM2;
    volatile uint32_t PATT2;
    uint32_t  RESERVED0;
    volatile uint32_t ECCR2;
} FSMC_Bank2_Register_t;

typedef struct GPIO_Register {
    volatile uint32_t CFGLR;
    volatile uint32_t CFGHR;
    volatile uint32_t INDR;
    volatile uint32_t OUTDR;
    volatile uint32_t BSHR;
    volatile uint32_t BCR;
    volatile uint32_t LCKR;
} GPIO_Register_t;

typedef struct AFIO_Register {
    volatile uint32_t ECR;
    volatile uint32_t PCFR1;
    volatile uint32_t EXTICR[4];
    uint32_t RESERVED0;
    volatile uint32_t PCFR2; 
} AFIO_Register_t;

typedef struct I2C_Register {
    volatile uint16_t CTLR1;
    uint16_t  RESERVED0;
    volatile uint16_t CTLR2;
    uint16_t  RESERVED1;
    volatile uint16_t OADDR1;
    uint16_t  RESERVED2;
    volatile uint16_t OADDR2;
    uint16_t  RESERVED3;
    volatile uint16_t DATAR;
    uint16_t  RESERVED4;
    volatile uint16_t STAR1;
    uint16_t  RESERVED5;
    volatile uint16_t STAR2;
    uint16_t  RESERVED6;
    volatile uint16_t CKCFGR;
    uint16_t  RESERVED7;
    volatile uint16_t RTR;
    uint16_t  RESERVED8;
} I2C_Register_t;

typedef struct IWDG_Register {
    volatile uint32_t CTLR;
    volatile uint32_t PSCR;
    volatile uint32_t RLDR;
    volatile uint32_t STATR;
} IWDG_Register_t;

typedef struct PWR_Register {
    volatile uint32_t CTLR;
    volatile uint32_t CSR;
} PWR_Register_t;

typedef struct RCC_Register {
    volatile uint32_t CTLR;
    volatile uint32_t CFGR0;
    volatile uint32_t INTR;
    volatile uint32_t APB2PRSTR;
    volatile uint32_t APB1PRSTR;
    volatile uint32_t AHBPCENR;
    volatile uint32_t APB2PCENR;
    volatile uint32_t APB1PCENR;
    volatile uint32_t BDCTLR;
    volatile uint32_t RSTSCKR;
    volatile uint32_t AHBRSTR;
    volatile uint32_t CFGR2;
} RCC_Register_t;

typedef struct RTC_Register {
    volatile uint16_t CTLRH;
    uint16_t  RESERVED0;
    volatile uint16_t CTLRL;
    uint16_t  RESERVED1;
    volatile uint16_t PSCRH;
    uint16_t  RESERVED2;
    volatile uint16_t PSCRL;
    uint16_t  RESERVED3;
    volatile uint16_t DIVH;
    uint16_t  RESERVED4;
    volatile uint16_t DIVL;
    uint16_t  RESERVED5;
    volatile uint16_t CNTH;
    uint16_t  RESERVED6;
    volatile uint16_t CNTL;
    uint16_t  RESERVED7;
    volatile uint16_t ALRMH;
    uint16_t  RESERVED8;
    volatile uint16_t ALRML;
    uint16_t  RESERVED9;
} RTC_Register_t;

typedef struct SDIO_Register {
    volatile uint32_t POWER;
    volatile uint32_t CLKCR;
    volatile uint32_t ARG;
    volatile uint32_t CMD;
    volatile uint32_t RESPCMD;
    volatile uint32_t RESP1;
    volatile uint32_t RESP2;
    volatile uint32_t RESP3;
    volatile uint32_t RESP4;
    volatile uint32_t DTIMER;
    volatile uint32_t DLEN;
    volatile uint32_t DCTRL;
    volatile uint32_t DCOUNT;
    volatile uint32_t STA;
    volatile uint32_t ICR;
    volatile uint32_t MASK;
    uint32_t  RESERVED0[2];
    volatile uint32_t FIFOCNT;
    uint32_t  RESERVED1[5];
    volatile uint32_t DCTRL2;
    uint32_t  RESERVED2[7];
    volatile uint32_t FIFO;
} SDIO_Register_t;

typedef struct SPI_Register {
    volatile uint16_t CTLR1;
    uint16_t  RESERVED0;
    volatile uint16_t CTLR2;
    uint16_t  RESERVED1;
    volatile uint16_t STATR;
    uint16_t  RESERVED2;
    volatile uint16_t DATAR;
    uint16_t  RESERVED3;
    volatile uint16_t CRCR;
    uint16_t  RESERVED4;
    volatile uint16_t RCRCR;
    uint16_t  RESERVED5;
    volatile uint16_t TCRCR;
    uint16_t  RESERVED6;
    volatile uint16_t I2SCFGR;
    uint16_t  RESERVED7;
    volatile uint16_t I2SPR;
    uint16_t  RESERVED8;
    volatile uint16_t HSCR;
    uint16_t  RESERVED9;
} SPI_Register_t;

typedef struct TIM_Register {
    volatile uint16_t CTLR1;
    uint16_t  RESERVED0;
    volatile uint16_t CTLR2;
    uint16_t  RESERVED1;
    volatile uint16_t SMCFGR;
    uint16_t  RESERVED2;
    volatile uint16_t DMAINTENR;
    uint16_t  RESERVED3;
    volatile uint16_t INTFR;
    uint16_t  RESERVED4;
    volatile uint16_t SWEVGR;
    uint16_t  RESERVED5;
    volatile uint16_t CHCTLR1;
    uint16_t  RESERVED6;
    volatile uint16_t CHCTLR2;
    uint16_t  RESERVED7;
    volatile uint16_t CCER;
    uint16_t  RESERVED8;
    volatile uint16_t CNT;
    uint16_t  RESERVED9;
    volatile uint16_t PSC;
    uint16_t  RESERVED10;
    volatile uint16_t ATRLR;
    uint16_t  RESERVED11;
    volatile uint16_t RPTCR;
    uint16_t  RESERVED12;
    volatile uint16_t CH1CVR;
    uint16_t  RESERVED13;
    volatile uint16_t CH2CVR;
    uint16_t  RESERVED14;
    volatile uint16_t CH3CVR;
    uint16_t  RESERVED15;
    volatile uint16_t CH4CVR;
    uint16_t  RESERVED16;
    volatile uint16_t BDTR;
    uint16_t  RESERVED17;
    volatile uint16_t DMACFGR;
    uint16_t  RESERVED18;
    volatile uint16_t DMAADR;
    uint16_t  RESERVED19;
    volatile uint16_t AUX;
    uint16_t  RESERVED20;
} TIM_Register_t;

typedef struct USART_Register {
    volatile uint16_t STATR;
    uint16_t  RESERVED0;
    volatile uint16_t DATAR;
    uint16_t  RESERVED1;
    volatile uint16_t BRR;
    uint16_t  RESERVED2;
    volatile uint16_t CTLR1;
    uint16_t  RESERVED3;
    volatile uint16_t CTLR2;
    uint16_t  RESERVED4;
    volatile uint16_t CTLR3;
    uint16_t  RESERVED5;
    volatile uint16_t GPR;
    uint16_t  RESERVED6;
    volatile uint16_t CTLR4;
    uint16_t  RESERVED7;
} USART_Register_t;

typedef struct WWDG_Register {
    volatile uint32_t CTLR;
    volatile uint32_t CFGR;
    volatile uint32_t STATR;
} WWDG_Register_t;

typedef struct EXTEN_Register {
    volatile uint32_t EXTEN_CTR;
    uint32_t  RESERVED0;
    volatile uint32_t EXTEN_CTR2;
} EXTEN_Register_t;

typedef struct OPA_Register {
    volatile uint32_t CR;
} OPA_Register_t;

typedef struct RNG_Register {
    volatile uint32_t CR;
    volatile uint32_t SR;
    volatile uint32_t DR;
} RNG_Register_t;

typedef struct DVP_Register {
    volatile uint8_t CR0;
    volatile uint8_t CR1;
    volatile uint8_t IER;
    volatile uint8_t Reserved0;        
    volatile uint16_t ROW_NUM;
    volatile uint16_t COL_NUM;
    volatile uint32_t DMA_BUF0;
    volatile uint32_t DMA_BUF1;
    volatile uint8_t IFR;
    volatile uint8_t STATUS;
    volatile uint16_t Reserved1;            
    volatile uint16_t ROW_CNT;
    volatile uint16_t Reserved2;           
    volatile uint16_t HOFFCNT;
    volatile uint16_t VST;
    volatile uint16_t CAPCNT;
    volatile uint16_t VLINE;
    volatile uint32_t DR;
} DVP_Register_t;

typedef struct USBHSD_Register {
    volatile uint8_t  CONTROL;
    volatile uint8_t  HOST_CTRL;
    volatile uint8_t  INT_EN;
    volatile uint8_t  DEV_AD;
    volatile uint16_t FRAME_NO;
    volatile uint8_t  SUSPEND;
    volatile uint8_t  RESERVED0;
    volatile uint8_t  SPEED_TYPE;
    volatile uint8_t  MIS_ST;
    volatile uint8_t  INT_FG;
    volatile uint8_t  INT_ST;
    volatile uint16_t RX_LEN;
    volatile uint16_t RESERVED1;
    volatile uint32_t ENDP_CONFIG;
    volatile uint32_t ENDP_TYPE;
    volatile uint32_t BUF_MODE;
    volatile uint32_t UEP0_DMA;               
    volatile uint32_t UEP1_RX_DMA;       
    volatile uint32_t UEP2_RX_DMA;       
    volatile uint32_t UEP3_RX_DMA;       
    volatile uint32_t UEP4_RX_DMA;       
    volatile uint32_t UEP5_RX_DMA;       
    volatile uint32_t UEP6_RX_DMA;       
    volatile uint32_t UEP7_RX_DMA;       
    volatile uint32_t UEP8_RX_DMA;      
    volatile uint32_t UEP9_RX_DMA;       
    volatile uint32_t UEP10_RX_DMA;      
    volatile uint32_t UEP11_RX_DMA;      
    volatile uint32_t UEP12_RX_DMA;      
    volatile uint32_t UEP13_RX_DMA;      
    volatile uint32_t UEP14_RX_DMA;      
    volatile uint32_t UEP15_RX_DMA;      
    volatile uint32_t UEP1_TX_DMA;       
    volatile uint32_t UEP2_TX_DMA;       
    volatile uint32_t UEP3_TX_DMA;       
    volatile uint32_t UEP4_TX_DMA;       
    volatile uint32_t UEP5_TX_DMA;      
    volatile uint32_t UEP6_TX_DMA;      
    volatile uint32_t UEP7_TX_DMA;       
    volatile uint32_t UEP8_TX_DMA;      
    volatile uint32_t UEP9_TX_DMA;       
    volatile uint32_t UEP10_TX_DMA;      
    volatile uint32_t UEP11_TX_DMA;      
    volatile uint32_t UEP12_TX_DMA;    
    volatile uint32_t UEP13_TX_DMA;      
    volatile uint32_t UEP14_TX_DMA;     
    volatile uint32_t UEP15_TX_DMA;      
    volatile uint16_t UEP0_MAX_LEN;
    volatile uint16_t RESERVED2;
    volatile uint16_t UEP1_MAX_LEN;
    volatile uint16_t RESERVED3;
    volatile uint16_t UEP2_MAX_LEN;
    volatile uint16_t RESERVED4;
    volatile uint16_t UEP3_MAX_LEN;
    volatile uint16_t RESERVED5;
    volatile uint16_t UEP4_MAX_LEN;
    volatile uint16_t RESERVED6;
    volatile uint16_t UEP5_MAX_LEN;
    volatile uint16_t RESERVED7;
    volatile uint16_t UEP6_MAX_LEN;
    volatile uint16_t RESERVED8;
    volatile uint16_t UEP7_MAX_LEN;
    volatile uint16_t RESERVED9;
    volatile uint16_t UEP8_MAX_LEN;
    volatile uint16_t RESERVED10;
    volatile uint16_t UEP9_MAX_LEN;
    volatile uint16_t RESERVED11;
    volatile uint16_t UEP10_MAX_LEN;
    volatile uint16_t RESERVED12;
    volatile uint16_t UEP11_MAX_LEN;
    volatile uint16_t RESERVED13;
    volatile uint16_t UEP12_MAX_LEN;
    volatile uint16_t RESERVED14;
    volatile uint16_t UEP13_MAX_LEN;
    volatile uint16_t RESERVED15;
    volatile uint16_t UEP14_MAX_LEN;
    volatile uint16_t RESERVED16;
    volatile uint16_t UEP15_MAX_LEN;
    volatile uint16_t RESERVED17;
    volatile uint16_t UEP0_TX_LEN;
    volatile uint8_t  UEP0_TX_CTRL;
    volatile uint8_t  UEP0_RX_CTRL;
    volatile uint16_t UEP1_TX_LEN;
    volatile uint8_t  UEP1_TX_CTRL;
    volatile uint8_t  UEP1_RX_CTRL;
    volatile uint16_t UEP2_TX_LEN;
    volatile uint8_t  UEP2_TX_CTRL;
    volatile uint8_t  UEP2_RX_CTRL;
    volatile uint16_t UEP3_TX_LEN;
    volatile uint8_t  UEP3_TX_CTRL;
    volatile uint8_t  UEP3_RX_CTRL;
    volatile uint16_t UEP4_TX_LEN;
    volatile uint8_t  UEP4_TX_CTRL;
    volatile uint8_t  UEP4_RX_CTRL;
    volatile uint16_t UEP5_TX_LEN;
    volatile uint8_t  UEP5_TX_CTRL;
    volatile uint8_t  UEP5_RX_CTRL;
    volatile uint16_t UEP6_TX_LEN;
    volatile uint8_t  UEP6_TX_CTRL;
    volatile uint8_t  UEP6_RX_CTRL;
    volatile uint16_t UEP7_TX_LEN;
    volatile uint8_t  UEP7_TX_CTRL;
    volatile uint8_t  UEP7_RX_CTRL;
    volatile uint16_t UEP8_TX_LEN;
    volatile uint8_t  UEP8_TX_CTRL;
    volatile uint8_t  UEP8_RX_CTRL;
    volatile uint16_t UEP9_TX_LEN;
    volatile uint8_t  UEP9_TX_CTRL;
    volatile uint8_t  UEP9_RX_CTRL;
    volatile uint16_t UEP10_TX_LEN;
    volatile uint8_t  UEP10_TX_CTRL;
    volatile uint8_t  UEP10_RX_CTRL;
    volatile uint16_t UEP11_TX_LEN;
    volatile uint8_t  UEP11_TX_CTRL;
    volatile uint8_t  UEP11_RX_CTRL;
    volatile uint16_t UEP12_TX_LEN;
    volatile uint8_t  UEP12_TX_CTRL;
    volatile uint8_t  UEP12_RX_CTRL;
    volatile uint16_t UEP13_TX_LEN;
    volatile uint8_t  UEP13_TX_CTRL;
    volatile uint8_t  UEP13_RX_CTRL;
    volatile uint16_t UEP14_TX_LEN;
    volatile uint8_t  UEP14_TX_CTRL;
    volatile uint8_t  UEP14_RX_CTRL;
    volatile uint16_t UEP15_TX_LEN;
    volatile uint8_t  UEP15_TX_CTRL;
    volatile uint8_t  UEP15_RX_CTRL;
} USBHSD_Register_t;

typedef struct USBHSH_Register {
    volatile uint8_t  CONTROL;
    volatile uint8_t  HOST_CTRL;
    volatile uint8_t  INT_EN;
    volatile uint8_t  DEV_AD;
    volatile uint16_t FRAME_NO;
    volatile uint8_t  SUSPEND;
    volatile uint8_t  RESERVED0;
    volatile uint8_t  SPEED_TYPE;
    volatile uint8_t  MIS_ST;
    volatile uint8_t  INT_FG;
    volatile uint8_t  INT_ST;
    volatile uint16_t RX_LEN;
    volatile uint16_t RESERVED1;
    volatile uint32_t HOST_EP_CONFIG;
    volatile uint32_t HOST_EP_TYPE;
    volatile uint32_t RESERVED2;
    volatile uint32_t RESERVED3;
    volatile uint32_t RESERVED4;
    volatile uint32_t HOST_RX_DMA;
    volatile uint32_t RESERVED5;
    volatile uint32_t RESERVED6;
    volatile uint32_t RESERVED7;
    volatile uint32_t RESERVED8;
    volatile uint32_t RESERVED9;
    volatile uint32_t RESERVED10;
    volatile uint32_t RESERVED11;
    volatile uint32_t RESERVED12;
    volatile uint32_t RESERVED13;
    volatile uint32_t RESERVED14;
    volatile uint32_t RESERVED15;
    volatile uint32_t RESERVED16;
    volatile uint32_t RESERVED17;
    volatile uint32_t RESERVED18;
    volatile uint32_t RESERVED19;
    volatile uint32_t HOST_TX_DMA;
    volatile uint32_t RESERVED20;
    volatile uint32_t RESERVED21;
    volatile uint32_t RESERVED22;
    volatile uint32_t RESERVED23;
    volatile uint32_t RESERVED24;
    volatile uint32_t RESERVED25;
    volatile uint32_t RESERVED26;
    volatile uint32_t RESERVED27;
    volatile uint32_t RESERVED28;
    volatile uint32_t RESERVED29;
    volatile uint32_t RESERVED30;
    volatile uint32_t RESERVED31;
    volatile uint32_t RESERVED32;
    volatile uint32_t RESERVED33;
    volatile uint16_t HOST_RX_MAX_LEN;
    volatile uint16_t RESERVED34;
    volatile uint32_t RESERVED35;
    volatile uint32_t RESERVED36;
    volatile uint32_t RESERVED37;
    volatile uint32_t RESERVED38;
    volatile uint32_t RESERVED39;
    volatile uint32_t RESERVED40;
    volatile uint32_t RESERVED41;
    volatile uint32_t RESERVED42;
    volatile uint32_t RESERVED43;
    volatile uint32_t RESERVED44;
    volatile uint32_t RESERVED45;
    volatile uint32_t RESERVED46;
    volatile uint32_t RESERVED47;
    volatile uint32_t RESERVED48;
    volatile uint32_t RESERVED49;
    volatile uint8_t  HOST_EP_PID;
    volatile uint8_t  RESERVED50;
    volatile uint8_t  RESERVED51;
    volatile uint8_t  HOST_RX_CTRL;
    volatile uint16_t HOST_TX_LEN;
    volatile uint8_t  HOST_TX_CTRL;
    volatile uint8_t  RESERVED52;
    volatile uint16_t HOST_SPLIT_DATA;
} USBHSH_Register_t;

typedef struct USBFSD_Register {
    volatile uint8_t  BASE_CTRL;
    volatile uint8_t  UDEV_CTRL;
    volatile uint8_t  INT_EN;
    volatile uint8_t  DEV_ADDR;
    volatile uint8_t  Reserve0;
    volatile uint8_t  MIS_ST;
    volatile uint8_t  INT_FG;
    volatile uint8_t  INT_ST;
    volatile uint16_t RX_LEN;
    volatile uint16_t Reserve1;
    volatile uint8_t  UEP4_1_MOD;
    volatile uint8_t  UEP2_3_MOD;
    volatile uint8_t  UEP5_6_MOD;
    volatile uint8_t  UEP7_MOD;
    volatile uint32_t UEP0_DMA;
    volatile uint32_t UEP1_DMA;
    volatile uint32_t UEP2_DMA;
    volatile uint32_t UEP3_DMA;
    volatile uint32_t UEP4_DMA;
    volatile uint32_t UEP5_DMA;
    volatile uint32_t UEP6_DMA;
    volatile uint32_t UEP7_DMA;
    volatile uint16_t UEP0_TX_LEN;
    volatile uint8_t  UEP0_TX_CTRL;
    volatile uint8_t  UEP0_RX_CTRL;
    volatile uint16_t UEP1_TX_LEN;
    volatile uint8_t  UEP1_TX_CTRL;
    volatile uint8_t  UEP1_RX_CTRL;
    volatile uint16_t UEP2_TX_LEN;
    volatile uint8_t  UEP2_TX_CTRL;
    volatile uint8_t  UEP2_RX_CTRL;
    volatile uint16_t UEP3_TX_LEN;
    volatile uint8_t  UEP3_TX_CTRL;
    volatile uint8_t  UEP3_RX_CTRL;
    volatile uint16_t UEP4_TX_LEN;
    volatile uint8_t  UEP4_TX_CTRL;
    volatile uint8_t  UEP4_RX_CTRL;
    volatile uint16_t UEP5_TX_LEN;
    volatile uint8_t  UEP5_TX_CTRL;
    volatile uint8_t  UEP5_RX_CTRL;
    volatile uint16_t UEP6_TX_LEN;
    volatile uint8_t  UEP6_TX_CTRL;
    volatile uint8_t  UEP6_RX_CTRL;
    volatile uint16_t UEP7_TX_LEN;
    volatile uint8_t  UEP7_TX_CTRL;
    volatile uint8_t  UEP7_RX_CTRL;
    volatile uint32_t Reserve2;
    volatile uint32_t OTG_CR;
    volatile uint32_t OTG_SR;
} USBFSD_Register_t;

typedef struct USBFSH_Register {
    volatile uint8_t   BASE_CTRL;
    volatile uint8_t   HOST_CTRL;
    volatile uint8_t   INT_EN;
    volatile uint8_t   DEV_ADDR;
    volatile uint8_t   Reserve0;
    volatile uint8_t   MIS_ST;
    volatile uint8_t   INT_FG;
    volatile uint8_t   INT_ST;
    volatile uint16_t  RX_LEN;
    volatile uint16_t  Reserve1;
    volatile uint8_t   Reserve2;
    volatile uint8_t   HOST_EP_MOD;
    volatile uint16_t  Reserve3;
    volatile uint32_t  Reserve4;
    volatile uint32_t  Reserve5;
    volatile uint32_t  HOST_RX_DMA;
    volatile uint32_t  HOST_TX_DMA;
    volatile uint32_t  Reserve6;
    volatile uint32_t  Reserve7;
    volatile uint32_t  Reserve8;
    volatile uint32_t  Reserve9;
    volatile uint32_t  Reserve10;
    volatile uint16_t  Reserve11;
    volatile uint16_t  HOST_SETUP;
    volatile uint8_t   HOST_EP_PID;
    volatile uint8_t   Reserve12;
    volatile uint8_t   Reserve13;
    volatile uint8_t   HOST_RX_CTRL;
    volatile uint16_t  HOST_TX_LEN;
    volatile uint8_t   HOST_TX_CTRL;
    volatile uint8_t   Reserve14;
    volatile uint32_t  Reserve15;
    volatile uint32_t  Reserve16;
    volatile uint32_t  Reserve17;
    volatile uint32_t  Reserve18;
    volatile uint32_t  Reserve19;
    volatile uint32_t  OTG_CR;
    volatile uint32_t  OTG_SR;
} USBFSH_Register_t;

typedef struct ETH_Register {
    volatile uint32_t MACCR;
    volatile uint32_t MACFFR;
    volatile uint32_t MACHTHR;
    volatile uint32_t MACHTLR;
    volatile uint32_t MACMIIAR;
    volatile uint32_t MACMIIDR;
    volatile uint32_t MACFCR;
    volatile uint32_t MACVLANTR;
    uint32_t RESERVED0[2];
    volatile uint32_t MACRWUFFR;
    volatile uint32_t MACPMTCSR;
    uint32_t RESERVED1[2];
    volatile uint32_t MACSR;
    volatile uint32_t MACIMR;
    volatile uint32_t MACA0HR;
    volatile uint32_t MACA0LR;
    volatile uint32_t MACA1HR;
    volatile uint32_t MACA1LR;
    volatile uint32_t MACA2HR;
    volatile uint32_t MACA2LR;
    volatile uint32_t MACA3HR;
    volatile uint32_t MACA3LR;
    uint32_t RESERVED2[14];
    volatile uint32_t MACCFG0;
    uint32_t RESERVED10[25];
    volatile uint32_t MMCCR;
    volatile uint32_t MMCRIR;
    volatile uint32_t MMCTIR;
    volatile uint32_t MMCRIMR;
    volatile uint32_t MMCTIMR;
    uint32_t RESERVED3[14];
    volatile uint32_t MMCTGFSCCR;
    volatile uint32_t MMCTGFMSCCR;
    uint32_t RESERVED4[5];
    volatile uint32_t MMCTGFCR;
    uint32_t RESERVED5[10];
    volatile uint32_t MMCRFCECR;
    volatile uint32_t MMCRFAECR;
    uint32_t RESERVED6[10];
    volatile uint32_t MMCRGUFCR;
    uint32_t RESERVED7[334];
    volatile uint32_t PTPTSCR;
    volatile uint32_t PTPSSIR;
    volatile uint32_t PTPTSHR;
    volatile uint32_t PTPTSLR;
    volatile uint32_t PTPTSHUR;
    volatile uint32_t PTPTSLUR;
    volatile uint32_t PTPTSAR;
    volatile uint32_t PTPTTHR;
    volatile uint32_t PTPTTLR;
    uint32_t RESERVED8[567];
    volatile uint32_t DMABMR;
    volatile uint32_t DMATPDR;
    volatile uint32_t DMARPDR;
    volatile uint32_t DMARDLAR;
    volatile uint32_t DMATDLAR;
    volatile uint32_t DMASR;
    volatile uint32_t DMAOMR;
    volatile uint32_t DMAIER;
    volatile uint32_t DMAMFBOCR;
    uint32_t RESERVED9[9];
    volatile uint32_t DMACHTDR;
    volatile uint32_t DMACHRDR;
    volatile uint32_t DMACHTBAR;
    volatile uint32_t DMACHRBAR;
} ETH_Register_t;

extern PFIC_Register_t *PFIC_register;
extern SysTick_Register_t *SysTick_register;

extern TIM_Register_t *TIM2_register;
extern TIM_Register_t *TIM3_register;
extern TIM_Register_t *TIM4_register;
extern TIM_Register_t *TIM5_register;
extern TIM_Register_t *TIM6_register;
extern TIM_Register_t *TIM7_register;
extern USART_Register_t *UART6_register;
extern USART_Register_t *UART7_register;
extern USART_Register_t *UART8_register;
extern RTC_Register_t *RTC_register;
extern WWDG_Register_t *WWDG_register;
extern IWDG_Register_t *IWDG_register;
extern SPI_Register_t *SPI2_register;
extern SPI_Register_t *SPI3_register;
extern USART_Register_t *USART2_register;
extern USART_Register_t *USART3_register;
extern USART_Register_t *UART4_register;
extern USART_Register_t *UART5_register;
extern I2C_Register_t *I2C1_register;
extern I2C_Register_t *I2C2_register;


extern BKP_Register_t *BKP_register;
extern PWR_Register_t *PWR_register;
extern DAC_Register_t *DAC_register;
extern AFIO_Register_t *AFIO_register;
extern EXTI_Register_t *EXTI_register;
extern GPIO_Register_t *GPIOA_register;
extern GPIO_Register_t *GPIOB_register;
extern GPIO_Register_t *GPIOC_register;
extern GPIO_Register_t *GPIOD_register;
extern GPIO_Register_t *GPIOE_register;
extern ADC_Register_t *ADC1_register;
extern ADC_Register_t *ADC2_register;
extern TIM_Register_t *TIM1_register;
extern SPI_Register_t *SPI1_register;
extern TIM_Register_t *TIM8_register;
extern USART_Register_t *USART1_register;
extern TIM_Register_t *TIM9_register;
extern TIM_Register_t *TIM10_register;
extern SDIO_Register_t *SDIO_register;
extern DMA_Register_t *DMA1_register;
extern DMA_Channel_Register_t *DMA1_Channel1_register;
extern DMA_Channel_Register_t *DMA1_Channel2_register;
extern DMA_Channel_Register_t *DMA1_Channel3_register;
extern DMA_Channel_Register_t *DMA1_Channel4_register;
extern DMA_Channel_Register_t *DMA1_Channel5_register;
extern DMA_Channel_Register_t *DMA1_Channel6_register;
extern DMA_Channel_Register_t *DMA1_Channel7_register;
extern DMA_Channel_Register_t *DMA1_Channel8_register;
extern DMA_Register_t *DMA2_register;
extern DMA_Channel_Register_t *DMA2_Channel1_register;
extern DMA_Channel_Register_t *DMA2_Channel2_register;
extern DMA_Channel_Register_t *DMA2_Channel3_register;
extern DMA_Channel_Register_t *DMA2_Channel4_register;
extern DMA_Channel_Register_t *DMA2_Channel5_register;
extern DMA_Channel_Register_t *DMA2_Channel6_register;
extern DMA_Channel_Register_t *DMA2_Channel7_register;
extern DMA_Channel_Register_t *DMA2_Channel8_register;
extern DMA_Channel_Register_t *DMA2_Channel9_register;
extern DMA_Channel_Register_t *DMA2_Channel10_register;
extern DMA_Channel_Register_t *DMA2_Channel11_register;
extern DMA_Register_t *DMA2_EXTEM_register;

extern RCC_Register_t *RCC_register;
extern EXTEN_Register_t *EXTEN_register;
extern USBFSD_Register_t *USBFSD_register;
extern USBFSH_Register_t *USBFSH_register;
extern USBHSD_Register_t *USBHSD_register;
extern USBHSH_Register_t *USBHSH_register;

extern CAN_Register_t *CAN1_register;
extern CAN_Register_t *CAN2_register;

extern ETH_Register_t *ETH_register;

}

class System {
public:
    enum class ClockBus {
        AHB = 0,
        APB1 = 1,
        APB2 = 2,
    };
    enum class ClockChannel{
        /* AHB. */
        DMA1 = 0,
        DMA2 = 1,
        SRAM = 2,
        CRC = 6,
        FSMC = 8,
        RNG = 9,
        SDIO = 10,
        USBHS = 11,
        USBFS = 12,
        DVP = 13,
        ETH_MAC = 14,
        ETH_MAC_TX = 15,
        ETH_MAC_RX = 16,
        BLES = 17,
        /* APB1. */
        TIM2 = 0 + 32,
        TIM3 = 1 + 32,
        TIM4 = 2 + 32,
        TIM5 = 3 + 32,
        TIM6 = 4 + 32,
        TIM7 = 5 + 32,
        USART6 = 6 + 32,
        USART7 = 7 + 32,
        USART8 = 8 + 32,
        WWDG = 11 + 32,
        SPI2 = 14 + 32,
        SPI3 = 15 + 32,
        USART2 = 17 + 32,
        USART3 = 18 + 32,
        USART4 = 19 + 32,
        USART5 = 20 + 32,
        I2C1 = 21 + 32,
        I2C2 = 22 + 32,
        USBD = 23 + 32,
        CAN1 = 25 + 32,
        CAN2 = 26 + 32,
        BKP = 27 + 32,
        PWR = 28 + 32,
        DAC = 29 + 32,
        /* APB2. */
        AFIO = 0 + 64,
        GPIOA = 2 + 64,
        GPIOB = 3 + 64,
        GPIOC = 4 + 64,
        GPIOD = 5 + 64,
        GPIOE = 6 + 64,
        ADC1 = 9 + 64,
        ADC2 = 10 + 64,
        TIM1 = 11 + 64,
        SPI1 = 12 + 64,
        TIM8 = 13 + 64,
        USART1 = 14 + 64,
        TIM9 = 19 + 64,
        TIM10 = 20 + 64,
    };

    enum class InterruptChannel{
        SysTick = 12,
        SoftwareInterrupt = 14,
        WWDG = 16,
        PVD = 17,
        TAMPER = 18,
        RTC = 19,
        FLASH = 20,
        RCC = 21,
        EXTI0 = 22,
        EXTI1 = 23,
        EXTI2 = 24,
        EXTI3 = 25,
        EXTI4 = 26,
        DMA1_CH1 = 27,
        DMA1_CH2 = 28,
        DMA1_CH3 = 29,
        DMA1_CH4 = 30,
        DMA1_CH5 = 31,
        DMA1_CH6 = 32,
        DMA1_CH7 = 33,
        ADC1_2 = 34,
        USB_HP_CAN1_TX = 35,
        USB_LP_CAN1_RX0 = 36,
        CAN1_RX1 = 37,
        CAN1_SCE = 38,
        EXTI9_5 = 39,
        TIM1_BRK = 40,
        TIM1_UP = 41,
        TIM1_TRG_COM = 42,
        TIM1_CC = 43,
        TIM2 = 44,
        TIM3 = 45,
        TIM4 = 46,
        I2C1_EV = 47,
        I2C1_ER = 48,
        I2C2_EV = 49,
        I2C2_ER = 50,
        SPI1 = 51,
        SPI2 = 52,
        USART1 = 53,
        USART2 = 54,
        USART3 = 55,
        EXTI15_10 = 56,
        RTC_Alarm = 57,
        USB_WakeUp = 58,
        TIM8_BRK = 59,
        TIM8_UP = 60,
        TIM8_TRG_COM = 61,
        TIM8_CC = 62,
        RNG = 63,
        SDIO = 65,
        TIM5 = 66,
        SPI3 = 67,
        USART4 = 68,
        USART5 = 69,
        TIM6 = 70,
        TIM7 = 71,
        DMA2_CH1 = 72,
        DMA2_CH2 = 73,
        DMA2_CH3 = 74,
        DMA2_CH4 = 75,
        DMA2_CH5 = 76,
        ETH = 77,
        ETH_WakeUp = 78,
        CAN2_TX = 79,
        CAN2_RX0 = 80,
        CAN2_RX1 = 81,
        CAN2_SCE = 82,
        OTG_FS = 83,
        USBHS_WakeUp = 84,
        USBHS = 85,
        DVP = 86,
        USART6 = 87,
        USART7 = 88,
        USART8 = 89,
        TIM9_BRK = 90,
        TIM9_UP = 91,
        TIM9_TRG_COM = 92,
        TIM9_CC = 93,
        TIM10_BRK = 94,
        TIM10_UP = 95,
        TIM10_TRG_COM = 96,
        TIM10_CC = 97,
        DMA2_CH6 = 98,
        DMA2_CH7 = 99,
        DMA2_CH8 = 100,
        DMA2_CH9 = 101,
        DMA2_CH10 = 102,
        DMA2_CH11 = 103,
    };

    enum class IORemapChannel {
        ETH_PTP_PPS = 0,
        TIM2_ITR = 1,
        SPI3 = 2,
        SWD = 3,
        MII_RMII_SELECT = 4,
        CAN2 = 5,
        ETH = 6,
        ADC2_ETRGREG = 7,
        ADC2_ETRGINJ = 8,
        ADC1_ETRGREG = 9,
        ADC1_ETRGINJ = 10,
        TIM5_CH4 = 11,
        EXT_CRYSTAL = 12,
        CAN1 = 13,
        TIM4 = 14,
        TIM3 = 15,
        TIM2 = 16,
        TIM1 = 17,
        USART3 = 18,
        USART2 = 19,
        USART1 = 20,
        I2C1 = 21,
        SPI1 = 22,
        USART8 = 23,
        USART7 = 24,
        USART6 = 25,
        USART5 = 26,
        USART4 = 27,
        FSMC_NADV = 28,
        TIM10 = 29,
        TIM9 = 30,
        TIM8 = 31,
    };

public:
    /* About clocks. */
    static bool setClockChannelStatus(ClockChannel channel,bool status);
    static bool getClockChannelStatus(ClockChannel channel);
    static unsigned int getClockChannelFrequency(ClockChannel channel);

    /* About interrupts. */
    static bool setInterruptChannelStatus(InterruptChannel channel,bool status);
    static bool setInterruptChannelStatus(int channel,bool status);
    static bool getInterruptChannelStatus(InterruptChannel channel);
    static bool getInterruptChannelStatus(int channel);

    /* GPIO remap. */
    static bool setAlternateFunctionIOStatus(int port_number,int pin_number,bool status);
    static bool setIORemapChannel(IORemapChannel remap_channel,unsigned int remap);

    static void delayMs(unsigned int nms);
};

#endif